"""
高性能文件系统增强模块
通过增强的缓存管理、线程池处理、事务日志记录和错误处理机制，实现了高性能、高可靠性和数据一致性的文件读写功能。
"""

#include <dokan.h>
#include <windows.h>
#include <iostream>
#include <map>
#include <mutex>
#include <thread>
#include <queue>
#include <list>
#include <algorithm>

// 缓存管理类
class CacheManager {
public:
    CacheManager(size_t maxSize) : maxSize_(maxSize) {}

    void AddToCache(const std::wstring& file, const std::vector<char>& data) {
        std::lock_guard<std::mutex> lock(mutex_);
        cache_[file] = data;
        usageList_.push_back(file);
        EnsureMaxSize();
    }

    void GetFromCache(const std::wstring& file, std::vector<char>& data) {
        std::lock_guard<std::mutex> lock(mutex_);
        auto it = cache_.find(file);
        if (it != cache_.end()) {
            data = it->second;
            usageList_.erase(std::remove(usageList_.begin(), usageList_.end(), file), usageList_.end());
            usageList_.push_back(file);
        }
    }

private:
    void EnsureMaxSize() {
        while (cache_.size() > maxSize_) {
            if (!usageList_.empty()) {
                std::wstring leastUsed = usageList_.front();
                cache_.erase(leastUsed);
                usageList_.pop_front();
            }
        }
    }

    std::map<std::wstring, std::vector<char>> cache_;
    std::list<std::wstring> usageList_;
    size_t maxSize_;
    std::mutex mutex_;
};

// 线程池类
class ThreadPool {
public:
    ThreadPool(size_t threads) : stop_(false) {
        for (size_t i = 0; i < threads; ++i) {
            workers_.emplace_back([this] {
                while (true) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(queueMutex_);
                        condition_.wait(lock, [this] { return stop_ || !tasks_.empty(); });
                        if (stop_ && tasks_.empty()) return;
                        task = std::move(tasks_.front());
                        tasks_.pop();
                    }
                    task();
                }
            });
        }
    }

    template<class F, class... Args>
    void Enqueue(F&& f, Args&&... args) {
        {
            std::unique_lock<std::mutex> lock(queueMutex_);
            if (stop_) throw std::runtime_error("Enqueued after stopping.");
            tasks_.emplace(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
        }
        condition_.notify_one();
    }

    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queueMutex_);
            stop_ = true;
        }
        condition_.notify_all();
        for (std::thread& worker : workers_) worker.join();
    }

private:
    std::vector<std::thread> workers_;
    std::queue<std::function<void()>> tasks_;
    std::mutex queueMutex_;
    std::condition_variable condition_;
    bool stop_;
};

// 事务日志类
class TransactionLog {
public:
    void LogOperation(const std::wstring& file, const std::vector<char>& data) {
        std::lock_guard<std::mutex> lock(mutex_);
        log_.push_back(std::make_pair(file, data));
    }

    void RecoverFromLog() {
        std::wcout << L"Recovering from transaction log..." << std::endl;
        for (const auto& entry : log_) {
            SyncToDisk(entry.first, entry.second);
        }
    }

private:
    void SyncToDisk(const std::wstring& file, const std::vector<char>& data) {
        HANDLE hFile = CreateFile(file.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile != INVALID_HANDLE_VALUE) {
            DWORD bytesWritten;
            WriteFile(hFile, data.data(), (DWORD)data.size(), &bytesWritten, NULL);
            CloseHandle(hFile);
        }
    }

    std::vector<std::pair<std::wstring, std::vector<char>>> log_;
    std::mutex mutex_;
};

// 全局对象
CacheManager cacheManager(1024 * 1024 * 1024); // 1GB缓存
ThreadPool threadPool(4); // 4个线程
TransactionLog transactionLog;

// 文件操作回调函数

NTSTATUS ReadFile(
    PDOKAN_FILE_INFO FileInfo,
    LPCVOID Buffer,
    DWORD BufferLength,
    LPDWORD BytesRead,
    LARGE_INTEGER Offset
) {
    std::wstring fullPath = GetFullPath(FileInfo->Context);

    std::vector<char> cachedData;
    cacheManager.GetFromCache(fullPath, cachedData);

    if (!cachedData.empty() && Offset.QuadPart < cachedData.size()) {
        size_t readLength = std::min((size_t)BufferLength, cachedData.size() - Offset.QuadPart);
        memcpy((void*)Buffer, cachedData.data() + Offset.QuadPart, readLength);
        *BytesRead = readLength;
        return STATUS_SUCCESS;
    }

    HANDLE hFile = CreateFile(fullPath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        return STATUS_ACCESS_DENIED;
    }

    DWORD bytesRead;
    if (!ReadFile(hFile, (LPVOID)Buffer, BufferLength, &bytesRead, NULL)) {
        CloseHandle(hFile);
        return STATUS_UNSUCCESSFUL;
    }

    CloseHandle(hFile);
    *BytesRead = bytesRead;

    // 更新缓存
    std::vector<char> data((char*)Buffer, (char*)Buffer + bytesRead);
    cacheManager.AddToCache(fullPath, data);

    return STATUS_SUCCESS;
}

NTSTATUS WriteFile(
    PDOKAN_FILE_INFO FileInfo,
    LPCVOID Buffer,
    DWORD NumberOfBytesToWrite,
    LPDWORD NumberOfBytesWritten,
    LARGE_INTEGER Offset
) {
    std::wstring fullPath = GetFullPath(FileInfo->Context);

    // 将数据写入缓存
    std::vector<char> data((char*)Buffer, (char*)Buffer + NumberOfBytesToWrite);
    cacheManager.AddToCache(fullPath, data);

    // 记录事务日志
    transactionLog.LogOperation(fullPath, data);

    // 通过线程池同步到磁盘
    threadPool.Enqueue([fullPath, data] {
        SyncToDisk(fullPath, data);
    });

    *NumberOfBytesWritten = NumberOfBytesToWrite;
    return STATUS_SUCCESS;
}

NTSTATUS FlushFileBuffers(
    PDOKAN_FILE_INFO FileInfo
) {
    std::wstring fullPath = GetFullPath(FileInfo->Context);

    std::vector<char> cachedData;
    cacheManager.GetFromCache(fullPath, cachedData);

    if (!cachedData.empty()) {
        SyncToDisk(fullPath, cachedData);
    }

    return STATUS_SUCCESS;
}

NTSTATUS Cleanup(
    PCWSTR FileName,
    PDOKAN_FILE_INFO FileInfo
) {
    std::wstring fullPath = GetFullPath(FileName);

    // 清理缓存
    cacheManager.AddToCache(fullPath, std::vector<char>());

    return STATUS_SUCCESS;
}

// 辅助函数：同步数据到磁盘
void SyncToDisk(const std::wstring& file, const std::vector<char>& data) {
    HANDLE hFile = CreateFile(file.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != INVALID_HANDLE_VALUE) {
        DWORD bytesWritten;
        WriteFile(hFile, data.data(), (DWORD)data.size(), &bytesWritten, NULL);
        CloseHandle(hFile);
    }
}